package tsv

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"time"
)

// 生成时间对齐的csv表格
// 时间对齐模块
type TsVals struct {
	begin    int64
	end      int64
	interval int64
	size     int64
	names    []string
	cols     [][]*float64 //row,col
	mapCol   map[string]int
}

// 指定列名
func NewTsVals(cols ...string) *TsVals {
	m := new(TsVals)
	if len(cols) > 0 {
		m.SetColumns(cols)
	}
	return m
}

// 设置列名
func (m *TsVals) SetColumns(cols []string) *TsVals {
	toReset := true
	if len(cols) == len(m.names) {
		if m.begin != 0 && m.end != 0 {
			toReset = true
		}
	}
	m.names = cols
	if toReset {
		m.Reset(m.begin, m.end, m.interval)
	}
	if m.mapCol == nil {
		m.mapCol = make(map[string]int)
	}
	clear(m.mapCol)
	for i, name := range cols {
		m.mapCol[name] = i
	}
	return m
}

//重置所有属性
func (m *TsVals) ResetAll(cols []string, begin, end, interval int64)*TsVals {
	clear(m.mapCol)
	for i, name := range cols {
		m.mapCol[name] = i
	}
	m.names = cols
	return m.Reset(begin, end, interval)
}

// 重置开始时间，结束时间，间隔
func (m *TsVals) Reset(begin, end, interval int64) *TsVals {
	if m.begin == begin && m.end == end && m.interval == interval {
		return m
	}
	m.begin = begin
	m.end = end
	m.interval = interval
	n := (m.end - m.begin)
	if m.interval > 0 {
		if n%m.interval == 0 {
			n = n / m.interval
		} else {
			n = n/m.interval + 1
		}
	}
	m.size = n
	nCol := len(m.names)
	m.cols = make([][]*float64, nCol)
	for i := range m.cols {
		m.cols[i] = make([]*float64, m.size)
	}
	return m.ResetData()
}

// 设置值
func (m *TsVals) Set(ts int64, col int, value float64) (err error) {
	i := (ts - m.begin)
	if m.interval > 0 {
		i /= m.interval
	}
	if i < 0{
		i = 0
	}
	if i >= m.size {
		return
	}

	row := m.cols[col]
	row[i] = &value
	return
}

// 根据列名设置值
func (m *TsVals) SetByName(ts int64, col string, value float64) (err error) {
	i, ok := m.mapCol[col]
	if !ok {
		return fmt.Errorf("column not found:%s", col)
	}
	return m.Set(ts, i, value)
}

// 重置数据
func (m *TsVals) ResetData() *TsVals {
	for _, row := range m.cols {
		for j := range row {
			row[j] = nil
		}
	}
	return m
}

// 填充值
func (m *TsVals) Fill() *TsVals {
	if len(m.cols) == 0 {
		return m
	}
	if len(m.cols[0]) == 0 {
		return m
	}
	for _, col := range m.cols {
		for j, v := range col[1:] {
			if v == nil {
				col[j+1] = col[j]
			}
		}
	}
	return m
}

// 保存为csv文件
func (m *TsVals) SaveCsv(fileName string) error {
	f, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer f.Close()
	err = m.WriteToCsv(f)
	if err != nil {
		return err
	}

	err = f.Sync()
	return err
}

// 将数据以csv格式写入writer
func (m *TsVals) WriteToCsv(writer io.Writer) error {
	buf := bufio.NewWriter(writer)
	for _, name := range m.names {
		buf.WriteByte(',')
		buf.WriteString(name)
	}
	buf.WriteByte('\n')

	//需要列转行
	for i := range m.cols[0] {
		if m.interval == 0 {
			buf.WriteString(time.Unix(m.begin+int64(i), 0).Format(" 2006-01-02 15:04:05"))
		} else {
			buf.WriteString(time.Unix(m.begin+int64(i)*m.interval, 0).Format(" 2006-01-02 15:04:05"))
		}
		for j := range m.names {
			buf.WriteByte(',')
			v := m.cols[j][i]
			if v == nil {
				continue
			}
			buf.WriteString(strconv.FormatFloat(*v, 'f', 2, 64))
		}
		buf.WriteByte('\n')
	}
	err := buf.Flush()
	return err
}

// 获取列数据
func (m *TsVals) Column(i int) []*float64 {
	return m.cols[i]
}

// 获取时间轴
func (m *TsVals) Times() []int64 {
	tms := make([]int64, m.size)
	step := m.interval
	if step == 0 {
		step = 1
	}
	for i := int64(0); i < (m.size); i++ {
		tms[i] = m.begin + i*step
	}
	return tms
}

// 获取列数
func (m *TsVals) Columns() []string {
	return m.names
}

// 获取数据大小
func (m *TsVals) Size() int {
	return int(m.size)
}
